/**
 * 
 */
package managedbeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import detallecarroejb.DetCarroEJBRemote;
import entidades.DetalleCarro;
import entidades.Producto;

/**
 * Esta es la clase Manage bean para el detalleCarro;
 * 
 * @author Fernando
 * 
 */

@ManagedBean(name = "MBDetalle")
@SessionScoped
public class MBDetalle implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /**
     * este atributo sirve para obtener los metodos del EJB de detalleCarro.
     */
    @EJB(name = "DCEJB", mappedName = "DCEJB")
    private DetCarroEJBRemote dejb;

    /**
     * Este atributo sirve para enviar informacion y atributos a los elementos
     * contenidos por el manage bean de producto.
     */
    @ManagedProperty(value = "#{MBTienda}")
    private MBProducto mbProducto;

    /**
     * Este atributo sirve para enviar informacion y atributos a los elementos
     * contenidos por el manage bean de Carro.
     */
    @ManagedProperty(value = "#{MBCarro}")
    private MBCarro mbCarro;

    /**
     * Variable auxiliar para iddetalle de tipo int.
     */
    private int idDetalle;
    /**
     * variable auxiliar para idcarro de tipo int.
     */
    private int idCarro;
    /**
     * variable auxiliar para idproducto de tipo String.
     */
    private String idProducto;
    /**
     * variable auxiliar para cantidad de tipo int.
     */
    private int cantidad;
    /**
     * variable tipo producto para realizar las operaciones con la ejb.
     */
    private Producto prod;
    /**
     * variable auxiliar para mantener el total del precio de los elementos en
     * el detalle del carro.
     */
    private int total;
    /**
     * variable auxiliar para mantener el total de items contenidos en el carro.
     */
    private int itemsCarro;
    /**
     * lista de los elementos que seran agregados a la BD via el ejb.
     */
    private List<DetalleCarro> listDC;
    /**
     * variable tipo producto para realizar las operaciones con la ejb.
     */
    private DetalleCarro detC;
    /**
     * lista de los elementos contenidos en el carro a visualizar en la .jsf.
     */
    private List<Producto> vistaC;

    /**
     * Este es el metodo asociado al postconstruct que inicializa todas
     * lvariables del manage bean.
     */
    @PostConstruct
    public void init() {
        detC = new DetalleCarro();
        prod = new Producto();
        vistaC = new ArrayList<Producto>();
        listDC = new ArrayList<DetalleCarro>();
        total = 0;
        itemsCarro = 0;
    }

    /**
     * Constructor por default.
     */
    public MBDetalle() {

    }

    /**
     * Chequea el carro, para ver si encuentra el producto en la lista si lo
     * encuentra, agrega uno a su cantidad, si no lo encuentra, lo agrega a la
     * lista con cantidad de uno, este add, solo se realiza desde el listado de
     * productos.
     * 
     * @param prodRecibido
     *            El producto objetivo que se va a agregar.
     */
    public void addToCart(Producto prodRecibido) {
        if (prodRecibido.getCantProd() > 0) {
            Producto auxProd = new Producto();
            auxProd.setCantProd(prodRecibido.getCantProd());
            auxProd.setDescProd(prodRecibido.getDescProd());
            auxProd.setIdProd(prodRecibido.getIdProd());
            auxProd.setNomProd(prodRecibido.getNomProd());
            auxProd.setPrecioProd(prodRecibido.getPrecioProd());
            if (!(vistaC.isEmpty())) {
                int cont = 0;
                for (Producto p : vistaC) {
                    if (p.getIdProd().equals(auxProd.getIdProd())) {
                        prodRecibido
                                .setCantProd(prodRecibido.getCantProd() - 1);
                        cont++;
                        p.setCantProd(p.getCantProd() + 1);
                        total = total + auxProd.getPrecioProd();
                        itemsCarro++;
                    }
                }
                if (cont == 0) {
                    vistaC.add(auxProd);
                    for (Producto p : vistaC) {
                        if (p.getIdProd().equals(auxProd.getIdProd())) {
                            prodRecibido
                                .setCantProd(prodRecibido.getCantProd() - 1);
                            p.setCantProd(1);
                            total = total + auxProd.getPrecioProd();
                            itemsCarro++;
                        }
                    }
                }
            } else {
                prodRecibido.setCantProd(prodRecibido.getCantProd() - 1);
                auxProd.setCantProd(1);
                total = total + auxProd.getPrecioProd();
                itemsCarro++;
                vistaC.add(auxProd);
            }
        }
    }

    /**
     * El metodo solo se usa al sumar desde la pagina del carro de compras,
     * busca comprobar el stock con la lista de productos de MBProducto, para
     * verificar que aun esta dentro del stock.
     * 
     * @param pSuma
     *            Objeto producto objetivo.
     */
    public void sumarProducto(Producto pSuma) {
        List<Producto> lAux = new ArrayList<Producto>();
        lAux = (List<Producto>) mbProducto.getListProd();
        for (Producto l : lAux) {
            if (l.getIdProd().equals(pSuma.getIdProd())) {
                if (l.getCantProd() > 0) {
                    pSuma.setCantProd(pSuma.getCantProd() + 1);
                    l.setCantProd(l.getCantProd() - 1);
                    total = total + pSuma.getPrecioProd();
                    itemsCarro++;
                }
            }
        }
        mbProducto.setListProd(lAux);
    }

    /**
     * El metodo solo se usa al restar desde la pagina del carro de compras,
     * busca comprobar la cantidad de productos restantes en el carro de compra,
     * y luego restar del carro y devolver al stock, en caso de que no queden
     * mas unidades, lo elimina del carro.
     * 
     * @param pResta
     *            Objeto producto objetivo.
     */
    public void restarProducto(Producto pResta) {
        List<Producto> lAux = new ArrayList<Producto>();
        lAux = (List<Producto>) mbProducto.getListProd();
        for (Producto l : lAux) {
            if (l.getIdProd().equals(pResta.getIdProd())) {
                if (pResta.getCantProd() >= 1) {
                    pResta.setCantProd(pResta.getCantProd() - 1);
                    l.setCantProd(l.getCantProd() + 1);
                    total = total - pResta.getPrecioProd();
                    itemsCarro--;
                }

                if (pResta.getCantProd() == 0) {
                    elimProducto(pResta);
                }
            }
        }
        mbProducto.setListProd(lAux);
    }

    /**
     * El metodo elimina de la lista de produtos en el carro el objeto objetivo,
     * y devuelve la cantidad restante al stock de la lista de productos.
     * 
     * @param pElim
     *            El objeto objetivo a eliminar.
     */
    public void elimProducto(Producto pElim) {
        List<Producto> lAux = new ArrayList<Producto>();
        lAux = (List<Producto>) mbProducto.getListProd();
        for (Producto l : lAux) {
            if (l.getIdProd().equals(pElim.getIdProd())) {
                itemsCarro = itemsCarro - pElim.getCantProd();
                total = total - (pElim.getCantProd() * pElim.getPrecioProd());
                l.setCantProd(l.getCantProd() + pElim.getCantProd());
                vistaC.remove(pElim);
            }
        }
        mbProducto.setListProd(lAux);
    }

    /**
     * Metodo que devuelve el url del detalle carro.
     * @return String detailcarro.jsf.
     */
    public String goToCheck() {
        return "detailcarro.jsf";
    }

    /**
     * El metodo obtiene el subtotal de cada producto en el carro, siendo este
     * su cantidad multiplicado su precio.
     * 
     * @param prod
     *            Objeto sobre el cual realizar el calculo.
     * @return Subtotal del objeto.
     */
    public int subTotal(Producto prod) {
        return prod.getCantProd() * prod.getPrecioProd();
    }

    /**
     * El metodo realiza todos los cambios necesarios en la base de datos
     * referentes a la compra (crear los nuevos elementos en detalle carro y
     * modificar el stock de los elementos de producto.
     * 
     * @return string con la pagina de redireccion.
     */
    public String realizarCompra() {
        FacesContext context = FacesContext.getCurrentInstance();
        if (mbCarro.getCarro().getUsuario() != null) {
            for (Producto lista : vistaC) {
                DetalleCarro detAux = new DetalleCarro();
                detAux.setCantidad(lista.getCantProd());
                detAux.setIdCarro(mbCarro.getCarro().getIdCarro());
                detAux.setIdProd(lista.getIdProd());
                dejb.AddDetCarro(detAux);
                context.addMessage(null, new FacesMessage("Venta exitosa!!"));
            }
            mbProducto.actualizarBD();
            logout();
            return "index";
        } else {
            context.addMessage(null, new FacesMessage("Venta fallida!!"));
            return "detailcarro";
        }

    }

    /**
     * El metodo cierra la sesion luego de una venta exitosa o luego de realizar
     * logout
     * 
     * @return La direccion index
     */
    public String logout() {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getExternalContext().invalidateSession();
        return "index";
    }

    /**
     * @return the dejb
     */
    public DetCarroEJBRemote getDejb() {
        return dejb;
    }

    /**
     * @param dejb the dejb to set
     */
    public void setDejb(DetCarroEJBRemote dejb) {
        this.dejb = dejb;
    }

    /**
     * @return the mbProducto
     */
    public MBProducto getMbProducto() {
        return mbProducto;
    }

    /**
     * @param mbProducto the mbProducto to set
     */
    public void setMbProducto(MBProducto mbProducto) {
        this.mbProducto = mbProducto;
    }

    /**
     * @return the mbCarro
     */
    public MBCarro getMbCarro() {
        return mbCarro;
    }

    /**
     * @param mbCarro the mbCarro to set
     */
    public void setMbCarro(MBCarro mbCarro) {
        this.mbCarro = mbCarro;
    }

    /**
     * @return the idDetalle
     */
    public int getIdDetalle() {
        return idDetalle;
    }

    /**
     * @param idDetalle the idDetalle to set
     */
    public void setIdDetalle(int idDetalle) {
        this.idDetalle = idDetalle;
    }

    /**
     * @return the idCarro
     */
    public int getIdCarro() {
        return idCarro;
    }

    /**
     * @param idCarro the idCarro to set
     */
    public void setIdCarro(int idCarro) {
        this.idCarro = idCarro;
    }

    /**
     * @return the idProducto
     */
    public String getIdProducto() {
        return idProducto;
    }

    /**
     * @param idProducto the idProducto to set
     */
    public void setIdProducto(String idProducto) {
        this.idProducto = idProducto;
    }

    /**
     * @return the cantidad
     */
    public int getCantidad() {
        return cantidad;
    }

    /**
     * @param cantidad the cantidad to set
     */
    public void setCantidad(int cantidad) {
        this.cantidad = cantidad;
    }

    /**
     * @return the prod
     */
    public Producto getProd() {
        return prod;
    }

    /**
     * @param prod the prod to set
     */
    public void setProd(Producto prod) {
        this.prod = prod;
    }

    /**
     * @return the total
     */
    public int getTotal() {
        return total;
    }

    /**
     * @param total the total to set
     */
    public void setTotal(int total) {
        this.total = total;
    }

    /**
     * @return the itemsCarro
     */
    public int getItemsCarro() {
        return itemsCarro;
    }

    /**
     * @param itemsCarro the itemsCarro to set
     */
    public void setItemsCarro(int itemsCarro) {
        this.itemsCarro = itemsCarro;
    }

    /**
     * @return the listDC
     */
    public List<DetalleCarro> getListDC() {
        return listDC;
    }

    /**
     * @param listDC the listDC to set
     */
    public void setListDC(List<DetalleCarro> listDC) {
        this.listDC = listDC;
    }

    /**
     * @return the detC
     */
    public DetalleCarro getDetC() {
        return detC;
    }

    /**
     * @param detC the detC to set
     */
    public void setDetC(DetalleCarro detC) {
        this.detC = detC;
    }

    /**
     * @return the vistaC
     */
    public List<Producto> getVistaC() {
        return vistaC;
    }

    /**
     * @param vistaC the vistaC to set
     */
    public void setVistaC(List<Producto> vistaC) {
        this.vistaC = vistaC;
    }

    /**
     * @return the serialversionuid
     */
    public static long getSerialversionuid() {
        return serialVersionUID;
    }

}
